<html>
    <head>
        <title>作用域插槽</title>
    </head>
    <body>
        <script>
            // 作用域插槽
                   /*
                        作用域插槽的作用是：
                            为了在父组件中“使用子组件的插槽”时，能够“访问到子组件”的数据。

                            为了实现这一点，我们需要“给插槽声明属性”（插槽属性），
                            
                            然后“在声明插槽时”(子组件模板中) “将属性绑定到子组件的相应数据上” (比如，props、data的property、计算属性等等，)

                            "作用域插槽"字面含义是： 让插槽拥有自己的作用域。，在作用域中可以访问插槽的数据（声明插槽的组件肯定给插槽属性传递数量了！！）
                            ,而插槽的数据就是插槽的属性（声明插槽的组件给插槽属性传递的值）,"插槽属性"
                   */     

                   /*
                        有时候让插槽内容能够访问组件（插槽的父组件）中才有的数据是很有用的。

                        例如：  假设一个带有如下模板的<current-user>组件：
                   */
                            /*
                                组件模板内容：

                                <span>
                                    <slot>{{user.lastName}}</slot>
                                </span>
                            */
                        // 我们可能想换掉备用内容，用名而非用姓来显示：
                            /*
                                <current-user>
                                    {{user.firstName}}
                                </current-user>
                            */

                    /*
                        然而上述代码不会正常工作，因为只有 <current-user>组件内部(作用域内)可以访问到user对象，
                        而我们提供的内容是在父级渲染的（在父级的模板内，也就是在父级的作用域内）。
                    */

                    /*
                        "如何让父级模板(父级作用域中)能访问到子级组件的模板(作用域中的数据)"？？


                        为了让user在父级的插槽内容中可用，我们可以将user作为一个<slot>元素的一个 attribute 绑定上去：
                    */
                            /*
                                <span>
                                    <slot v-bind:user="user">  // 组件模板中，声明插槽属性(user可能来自组件的data属性或计算属性，或者是props属性传递过来的)
                                        {{user.lastName}}
                                    </slot>
                                </span>
                            */
                    /*
                        绑定在<slot>元素上的 attribute 被称为 "插槽属性(prop)"。

                        现在在父级作用域中，我们可以使用带值得 v-slot 来声明我们定义的"插槽属性"的名字：
                    */
                            /*
                                <current-user>
                                    <template v-slot:default="slotProps">  // 这里给插槽的属性集合对象，起了一个别名 slotProps，通过插槽的属性集合实例，可以访问到插槽属性
                                        {{ slotProps.user.firstName}}
                                    </template>
                                </current-user>


                                在这个例子中，我们选择将"包含插槽所有属性的对象"命名为 slotProps ，但你也可以使用任何你喜欢的名字
                            */


                //1、组件"只有默认插槽"的缩写语法：
                            /*
                                在上述情况下，当被提供的内容"只有默认插槽时"，组件的标签才可以被当做插槽模板来使用。

                                这样我们就可以把 v-slot 直接用在组件上：
                            */
                                    /*
                                        组件只有默认操作，就直接把　v-slot 指令写在组件标签里就好了，不用单独写一个<template>标签来表示"插槽模板"了。
                                        <current-user v-slot:defaut="slotProps">
                                            {{slotProps.user.firstName}}
                                        </current-user>
                                    */

                            /*
                                这种写法还可以更简单。
                                就像假定未指明去向的内容对应默认插槽一样，"不带参数的v-slot 被假定对应默认插槽"：
                            */
                                     /*
                                        v-slot指令，如果没有参数，那么它就对应"默认插槽"

                                        <current-user v-slot="slotProps">
                                            {{slotProps.user.firstName}}
                                        </current-user>
                                     */

                             /*
                                 注意：
                                      组件"只有默认插槽时"的"缩写语法" 不能和具名插槽混用，因为它会导致"作用域不明确"
                             */
                                        /*
                                            此用法大错特错！！   用了只有默认插槽的缩写语法，就只有默认插槽！！！
                                            <!-- 无效，会导致警告 -->

                                            <current-user v-slot="slotProps">
                                                {{ slotProps.user.firstName }}
                                            <template v-slot:other="otherSlotProps">
                                                slotProps is NOT available here
                                            </template>
                                            </current-user>
                                        */

                            /*
                                只要出现"多个插槽"， 请始终为多有的插槽使用完整的基于<template>标签的"插槽使用语法".
                            */
                                        /*
                                            一个组件有多个插槽，在使用时一定要用<template>标签，并且使用 v-slot指令，外加插槽名称作为参数来使用插槽、引用插槽属性。

                                            <current-user>
                                                <template v-slot:default="slotProps">
                                                    {{ slotProps.user.firstName}}
                                                </template>

                                                <template v-slot:other="otherSlotProps">
                                                    {{ otherSlotProps.user.firstName }}
                                                </template>
                                            </current-ueser>
                                        */
                 
                                        
                // 2、解构插槽属性(Prop)
                            /*
                                作用域插槽的内部工作原理是将你的插槽内容包裹在一个"拥有单个参数的函数中":

                                当你"使用作用域插槽"时，
                                等于是告诉Vue,"我要将插槽内容包裹在一个函数中，并且函数有个参数，
                                             这个参数是插槽声明的所有属性的集合对象，而且我要给这个参数起个别名，比如soltProps
                                             你vue在渲染时，你就调用这个函数，然后将插槽实例中的所有"插槽属性"封装成对象(其实就是插槽的实例对象)传入这个函数，
                                             根据这个函数的返回值来渲染插槽内容，"
                            */
                                     
                                            function(slotProps){
                                                // 插槽内容(注意此时插槽内容已经可以访问slotProps对象)

                                                // 将插槽内容返回给父级
                                            }

                            /*
                                这意味着 v-slot 的值实际上是任何能够作为函数定义中的参数的JavaScript表达式。
                                所以在支持的环境下( "单文件组件" 或 "现代浏览器")，你也可以使用ES6 的解构语法来"解构插槽属性集合对象"

                                例如：
                            */
                                        /*
                                            <current-user v-slot="{user}">  对插槽属性集合对象进行解构，可以"直接访问插槽属性"
                                                    {{ user.name }}
                                            </current-user>
                                        */

                            /*
                                这样可以使模板更加简洁，尤其是在该插槽提提供了多个插槽属性时。

                                它同样开启了prop 重命名等其他可能：

                                例如： 将插槽属性 user 重命名为 person
                            */
                                        /*
                                            <current-user v-slot="{user:person}">
                                                {{ person.name}}
                                            </current-user>
                                        */
                                            
                            /*
                                你甚至可以定义后备内容，用于插槽属性是undefined的情况：

                                        <current-user v-slot="{user={firstName:'Guest'}}">
                                            {{ user.firstName }}
                                        </current-user>
                            */
                                            
                        
                         
        </script>
    </body>
</html>